﻿#region References
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.ComponentModel;
using System.Threading;
using System.Media;

using DevExpress.XtraEditors;
#endregion

namespace Autumoon.OpenSource.TicketWatcher
{
    public partial class MainXtraForm : XtraForm
    {
        #region Fields and Properties
        private DateTime _startDateTime = DateTime.Now;
        private System.Windows.Forms.Timer _timeUsedTimer = null;
        private System.Windows.Forms.Timer _watchTimer = null;
        private WebClient _webClient = null;
        private SmtpClient _smtpClient = null;
        private bool _forceRestart = false;
        private string _semicolon = ";";
        #endregion

        #region Constructors
        public MainXtraForm()
        {
            InitializeComponent();

            this.Text
                = this.notifyIcon.Text
                = String.Format("{0} V{1}", Application.ProductName, Application.ProductVersion.TrimEnd(".0".ToCharArray()));

            this.InitializeTimer();
        }
        #endregion

        #region Public Methods
        #endregion

        #region Internal Methods
        #endregion

        #region Protected Methods
        #endregion

        #region Private Methods
        private void InitializeTimer()
        {
            this._timeUsedTimer = new System.Windows.Forms.Timer();
            this._timeUsedTimer.Interval = 1 * 60 * 1000;
            this._timeUsedTimer.Tick += new EventHandler(this.timeUsedTimer_Tick);
            this._timeUsedTimer.Start();

            this._watchTimer = new System.Windows.Forms.Timer();
            this._watchTimer.Tick += new EventHandler(this.watchTimer_Tick);
        }

        private void InitializeClient()
        {
            this._webClient = new WebClient();
            this._webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(this.webClient_DownloadStringCompleted);

            this._smtpClient = new SmtpClient(this.smtpTextEdit.Text.Trim(), (int)this.portSpinEdit.Value);
            this._smtpClient.UseDefaultCredentials = false;
            this._smtpClient.Credentials = new NetworkCredential(this.senderTextEdit.Text.Trim(), this.passwordTextEdit.Text);
            this._smtpClient.EnableSsl = this.sslCheckEdit.Checked;
            this._smtpClient.SendCompleted += new SendCompletedEventHandler(this.smtpClient_SendCompleted);
        }

        private void ValidateCondition()
        {
        }

        private void StatusLog(string statusMessage)
        {
            if (String.IsNullOrEmpty(statusMessage))
            {
                return;
            }

            this.statusListBox.Items.Insert(0, statusMessage);
        }

        private void PlayBeep()
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            this.Activate();

            for (int index = 0; index < 5; index++)
            {
                SystemSounds.Beep.Play();

                Thread.Sleep(500);
            }
        }

        private void Watch()
        {
            try
            {
                this._watchTimer.Interval = (int)this.intervalSpinEdit.Value * 60 * 1000;
                this._watchTimer.Stop();

                this.ValidateCondition();

                this.progressPictureEdit.Visible = true;

                this.statusListBox.Items.Insert(0, "Initialization.");

                this.InitializeClient();

                this.statusListBox.Items.Insert(0, "Start to watch.");
                this._webClient.DownloadStringAsync(new Uri(this.watchingPageUrlTextEdit.Text.Trim()));
            }
            catch (ValidationException exception)
            {
                XtraMessageBox.Show(exception.Message, "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
        }
        #endregion

        #region Delegates and Events
        private void MainXtraForm_Load(object sender, System.EventArgs e)
        {
        }

        private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            this.Activate();
        }

        private void watchSimpleButton_Click(object sender, EventArgs e)
        {
            this.Watch();
        }

        private void timeUsedTimer_Tick(object sender, EventArgs e)
        {
            int minutes = (int)TimeSpan.FromTicks((DateTime.Now - this._startDateTime).Ticks).TotalMinutes;

            this.statusGroupControl.Text = String.Format("Status (Time Used: {0} {1})", minutes.ToString(), ((int)minutes > 1 ? "Minutes" : "Minute"));
        }

        private void watchTimer_Tick(object sender, EventArgs e)
        {
            this.Watch();
        }

        private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            bool abort = false;

            if (e.Error != null)
            {
                this.statusListBox.Items.Insert(0, "Page content download failed: " + e.Error.Message);

                abort = true;
            }
            else
            {
                this.statusListBox.Items.Insert(0, "Page content is downloaded succeed.");

                string[] keywords = this.keywordsTextEdit.Text.Split(this._semicolon.ToCharArray());
                bool containsKeyword = false;

                foreach (string keyword in keywords)
                {
                    if (e.Result.Contains(keyword))
                    {
                        containsKeyword = true;

                        break;
                    }
                }

                abort = !containsKeyword;
            }

            if (abort)
            {
                this.statusListBox.Items.Insert(0, "Page content doesn't contain keyword.");

                this._watchTimer.Start();

                return;
            }

            this.statusListBox.Items.Insert(0, "Page content CONTAINS keyword.");

            this.PlayBeep();

            string pageContent = e.Result.Trim();

            try
            {
                string[] receivers = this.receiversTextEdit.Text.Split(this._semicolon.ToCharArray());

                foreach (string receiver in receivers)
                {
                    MailMessage mail = new MailMessage(this.senderTextEdit.Text.Trim(), receiver) { Subject = this.subjectTextEdit.Text.Trim() };
                    mail.Priority = MailPriority.High;

                    if (this.bodyComboBoxEdit.SelectedIndex == 0)
                    {
                        mail.Body = this.watchingPageUrlTextEdit.Text.Trim();
                    }
                    else if (this.bodyComboBoxEdit.SelectedIndex == 1)
                    {
                        mail.Body = e.Result.Trim();
                        mail.IsBodyHtml = true;
                    }

                    this.statusListBox.Items.Insert(0, "Start to send email.");

                    this._smtpClient.SendAsync(mail, null);
                }
            }
            catch (Exception ex)
            {
                this.statusListBox.Items.Insert(0, "Exception: " + ex.Message);

                this._watchTimer.Start();
            }
        }

        private void smtpClient_SendCompleted(object sender, AsyncCompletedEventArgs e)
        {
            this.progressPictureEdit.Visible = false;

            if (this._forceRestart)
            {
                this._forceRestart = false;

                return;
            }

            if (e.Error == null)
            {
                this.statusListBox.Items.Insert(0, "Send email successfully.");

                this._watchTimer.Stop();
            }
            else
            {
                this.statusListBox.Items.Insert(0, "Send email failed: " + e.Error.Message);
            }
        }

        private void sslCheckEdit_CheckedChanged(object sender, EventArgs e)
        {
            this.portSpinEdit.Value = (this.sslCheckEdit.Checked ? 465 : 25);
        }

        private void MainXtraForm_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
            }
        }

        private void MainXtraForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (XtraMessageBox.Show("Are you sure to exit?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes)
            {
                e.Cancel = true;
            }
        }
        #endregion
    }
}